package com.unionServer.unpack;

import org.dom4j.Attribute;
import org.dom4j.Element;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.util.*;

import lombok.extern.slf4j.Slf4j;

/**
 * @description:
 * @author: wangxinal
 * @time: 2022/1/13 14:53
 */
@Slf4j
public class Fix8583InterpretiveParser {

    private LinkedList<Fix8583InterpretiveParser.CacheItem> cacheList;
    private String encode = null;
    protected Element channelRoot = null;
    private String bitMapEncode = null;
    private boolean isCompress = true;
    private boolean logDetail = true;
    private ThreadLocal<IVarLengthEncoder> varPolicy = new ThreadLocal();
    private WeakHashMap<String, IVarLengthEncoder> encoders;


    protected HashMap<String, Object> doParse(byte[] msgs) throws Exception {
        HashMap<String, Object> reportMap = new HashMap();
        this.cacheList = new LinkedList();
        if (log.isDebugEnabled()) {
            log.debug("FIX报文解析数据：\n" + formatToHex(msgs));
        }

        this.parseReport(msgs, reportMap);
        if (log.isDebugEnabled()) {
            log.debug("FIX报文解析结果：\n" + reportMap);
        }

        return reportMap;
    }
    private void parseReport(byte[] msgs, HashMap<String, Object> map) throws Exception {
        BufferedInputStream in = null;
        in = new BufferedInputStream(new ByteArrayInputStream(msgs));
        this.encode = this.channelRoot.attributeValue("encoding");
        if (this.channelRoot.attributeValue("bitMapEncode") == null) {
            this.bitMapEncode = "default";
        } else {
            this.bitMapEncode = this.channelRoot.attributeValue("bitMapEncode");
        }

        Element fixmap = this.channelRoot.element("fixmap");
        if (fixmap == null) {
            fixmap = this.channelRoot;
        }

        Iterator itr = fixmap.elementIterator();

        while(itr.hasNext()) {
            Element curNode = (Element)itr.next();
            String mid = curNode.attributeValue("metadataid");
            if ("BH_8583_BITMAP".equalsIgnoreCase(mid)) {
                //this.parse8583(curNode, in, map);
            } else {
                this.parseItem(curNode, in, map, -1, false);
            }
        }

    }

    private void parseItem(Element node, BufferedInputStream in, HashMap<String, Object> map, int fieldIndex, boolean isCalledByLazyProcess) throws Exception {
        Properties pro = getProperties(node);
        String type = node.attributeValue("type")!=null? node.attributeValue("type") : node.attributeValue("metadataid") ;
        boolean isLLVAR = "LLVAR".equalsIgnoreCase(type);
        boolean isLLLVAR = "LLLVAR".equalsIgnoreCase(type);
        boolean isLazyParse = node.attributeValue("lazyParse")!=null? Boolean.parseBoolean(node.attributeValue("lazyParse")) : false;
        int lenDataLen = -1;
        if (isLLVAR) {
            lenDataLen =  2;
        } else if (isLLLVAR) {
            lenDataLen =  3;
        }


    }
    private boolean isSwitch(Element element) {
        return element != null && element.attributeValue("switchfield") != null && element.attributeValue("switchmode") != null;
    }
        public Properties getProperties(Element node) {
        Iterator attrs = node.attributeIterator();
        Properties p = new Properties();

        while(attrs.hasNext()) {
            Attribute attr = (Attribute)attrs.next();
            String attrName = attr.getName();
            String attrValue = attr.getValue();
            p.put(attrName, attrValue);
        }

        return p;
    }


    public void setCompress(boolean isCompress) {
        this.isCompress = isCompress;
    }
    public boolean isCompress() {
        return this.isCompress;
    }
    public static String formatToHex(byte[] data) {
        StringBuffer sb = new StringBuffer();
        int i = 0;

        try {
            while(i < data.length) {
                int length = i + 16 < data.length ? 16 : data.length - i;
                byte[] frag = new byte[length];
                System.arraycopy(data, i, frag, 0, length);
                String hexStr = toHexStr(frag);
                String s = String.format("%4d--%4d\t:\t%-48s;%s\n", i + 1, i + length, hexStr, new String(frag));
                sb.append(s);
                i += length;
            }
        } catch (Throwable var7) {
            log.error("formatToHex error : ", var7);
        }

        return sb.toString();
    }

    public static String toHexStr(byte[] frag) {
        if (frag == null) {
            return "";
        } else {
            int len = frag.length;
            StringBuffer sb = new StringBuffer(len * 2);

            for(int i = 0; i < len; ++i) {
                String temp = Integer.toHexString(255 & frag[i]);
                if (temp.length() < 2) {
                    sb.append(0);
                }

                sb.append(temp.toUpperCase()).append(" ");
            }

            return sb.toString();
        }
    }

    class CacheItem {
        byte[] data;
        Element element;
        int fieldNo;
        String type;
        int len;

        CacheItem() {
        }
    }
}
